﻿Namespace ObjManagement
    Public Module GeneralFunctions
        Public Function CloneObject(ByVal Source As Object) As Object
            If Source Is Nothing Then
                Return Nothing
            End If
            If Source.GetType.IsValueType Or Source.GetType Is GetType(System.String) Then
                Return Source
            Else
                Dim Destination As Object = Activator.CreateInstance(Source.GetType)
                If Not Source.GetType.GetInterface("IEnumerable", True) Is Nothing AndAlso Not Source.GetType.GetInterface("ICloneable", True) Is Nothing Then
                    'Se l'oggetto è una lista clonabile, la clono
                    Destination = CType(Source, ICloneable).Clone
                    Return Destination
                End If
                If Source.GetType.GetInterface("IClonable", True) IsNot Nothing Then
                    'Se l'oggetto da clonare è clonabile, lo clono direttamente
                    Destination = CType(Source, ICloneable).Clone
                    Return Destination
                Else
                    For Each PropInfo As System.Reflection.PropertyInfo In Destination.GetType.GetProperties
                        If PropInfo.CanWrite = True Then
                            If PropInfo.GetType.GetInterface("IClonable", True) IsNot Nothing Then
                                Dim ClonObj As ICloneable = CType(PropInfo.GetValue(Source, Nothing), ICloneable)
                                PropInfo.SetValue(Destination, ClonObj.Clone, Nothing)
                            Else
                                PropInfo.SetValue(Destination, CloneObject(PropInfo.GetValue(Source, Nothing)), Nothing)
                            End If
                        End If
                    Next
                    Return Destination
                End If
            End If
        End Function
    End Module
End Namespace
